package com.winit.flow.web;

import com.winit.common.base.bean.ExecuteResult;
import com.winit.common.base.web.BaseController;
import com.winit.flow.manager.FlowManager;
import com.winit.flow.model.Flow;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Api(value = "flow", tags = {"flow"}, description = "flow")
@RestController
@RequestMapping("/api/v1/flow")
public class FlowController extends BaseController {
    private static Logger log = LoggerFactory.getLogger(FlowController.class);


    @Autowired
    private FlowManager flowManager;


    @RequestMapping(value = "/createFlow", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "创建")
    @ResponseBody
    public Map createFlow(@RequestBody Flow flow) {
        ExecuteResult rs = this.flowManager.createFlow(flow);
        return this.getRtn(rs.getCode(), rs.getDesc(), rs.getData());
    }


    private static final class UpdateReqFlowContentParams {
        private String flowId;
        private String reqId;
        private Map<String, Object> attrs;

        public String getFlowId() {
            return flowId;
        }

        public void setFlowId(String flowId) {
            this.flowId = flowId;
        }

        public String getReqId() {
            return reqId;
        }

        public void setReqId(String reqId) {
            this.reqId = reqId;
        }

        public Map<String, Object> getAttrs() {
            return attrs;
        }

        public void setAttrs(Map<String, Object> attrs) {
            this.attrs = attrs;
        }
    }

    @RequestMapping(value = "/updateReqFlowContent", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "req 更新flow")
    @ResponseBody
    public Map updateReqFlowContent(@RequestBody UpdateReqFlowContentParams updateReqFlowContentParams) {
        ExecuteResult executeResult = null;
        String flowId = updateReqFlowContentParams.getFlowId();
        String reqId = updateReqFlowContentParams.getReqId();
        Map<String, Object> attrs = updateReqFlowContentParams.getAttrs();
        if (StringUtils.isEmpty(flowId) || StringUtils.isEmpty(reqId) || null == attrs) {
            return this.getRtn(BaseController.REQUEST_ERROR, "所有参数不能为空");
        }
        executeResult = this.flowManager.updateReqFlowContent(flowId, attrs, reqId, "UPDATE");
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }

    @RequestMapping(value = "/relateWithFlow", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "req关联flow")
    @ResponseBody
    public Map relateWithFlow(@ApiParam(value = "flowId", required = true) @RequestParam(value = "flowId", required = true) String flowId,
                              @ApiParam(value = "reqId", required = true) @RequestParam(value = "reqId", required = true) String reqId) {

        ExecuteResult executeResult = this.flowManager.relateWithFlow(flowId, reqId);
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }

    @RequestMapping(value = "/dissociateWithFlow", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "req解除关联/重置flow")
    @ResponseBody
    public Map dissociateWithFlow(@ApiParam(value = "flowId", required = true) @RequestParam(value = "flowId", required = true) String flowId,
                                  @ApiParam(value = "reqId", required = true) @RequestParam(value = "reqId", required = true) String reqId) {

        ExecuteResult executeResult = this.flowManager.dissociateWithFlow(flowId, reqId);
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }


    @RequestMapping(value = "/deleteFlow", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "物理删除flow")
    @ResponseBody
    public Map deleteFlow(@ApiParam(value = "flowId", required = true) @RequestParam(value = "flowId", required = true) String flowId) {
        ExecuteResult executeResult = this.flowManager.deleteFlow(flowId);
        return this.getRtn(executeResult.getCode(), executeResult.getDesc());
    }

    public static final class FlowTreeNode implements Serializable {
        private String id;
        private String type = "1-flow frame, 2-flow";
        private Object metaData;
        private String level;
        private String parentId;
        private String isDel;
        private String name;
        private String status;
        private List<FlowTreeNode> children = new ArrayList<>();

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public Object getMetaData() {
            return metaData;
        }

        public void setMetaData(Object metaData) {
            this.metaData = metaData;
        }

        public List<FlowTreeNode> getChildren() {
            return children;
        }

        public void setChildren(List<FlowTreeNode> children) {
            this.children = children;
        }

        public String getLevel() {
            return level;
        }

        public void setLevel(String level) {
            this.level = level;
        }

        public String getParentId() {
            return parentId;
        }

        public void setParentId(String parentId) {
            this.parentId = parentId;
        }

        public String getIsDel() {
            return isDel;
        }

        public void setIsDel(String isDel) {
            this.isDel = isDel;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getStatus() {
            return status;
        }

        public void setStatus(String status) {
            this.status = status;
        }
    }


    @RequestMapping(value = "/getFlowTree", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取flow tree")
    @ResponseBody
    public Map getFlowTree(@ApiParam(value = "flowFrameId") @RequestParam(value = "flowFrameId", required = false) String flowFrameId,
                           @ApiParam(value = "reqId") @RequestParam(value = "reqId", defaultValue = "-1") String reqId) {

        FlowTreeNode flowTreeNode = this.flowManager.getFlowTree(flowFrameId, reqId);
        return this.getRtn("0", "success", flowTreeNode);
    }

    @RequestMapping(value = "/getFlowTreeNode", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取flow tree node")
    @ResponseBody
    public Map getFlowTreeNode(@ApiParam(value = "flowId") @RequestParam(value = "flowId", required = false) String flowId) {
        FlowTreeNode flowTreeNode = this.flowManager.getFlowTreeNode(flowId);
        return this.getRtn("0", "success", flowTreeNode);
    }

    @RequestMapping(value = "/getFlowDetail", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获得指定flow")
    @ResponseBody
    public Map getFlowDetail(@ApiParam(value = "flowId", required = true) @RequestParam(value = "flowId", required = true) String flowId,
                             @ApiParam(value = "reqId,缺省为-1", required = false) @RequestParam(value = "reqId", defaultValue = "-1") String reqId) {

        Flow flow = null;
        try {
            flow = this.flowManager.getFlowDetail(flowId, reqId);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return this.getRtn("1", e.getMessage());
        }
        return this.getRtn("0", "success", flow);
    }


    @RequestMapping(value = "/getReqFlows", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取req关联的flow列表")
    @ResponseBody
    public Map getReqFlows(@ApiParam(value = "reqId", required = true) @RequestParam(value = "reqId", required = true) String reqId,
                           @ApiParam(value = "是否返回flow的attr  0 是 1 否，默认不返回", required = false) @RequestParam(value = "withAttr", required = false) String withAttr) {
        if (StringUtils.isEmpty(withAttr)) {
            withAttr = "1";
        }
        List<Flow> flows = this.flowManager.getReqFlows(reqId, withAttr);
        if (flows == null) {
            flows = new ArrayList<>();
        }
        return this.getRtn("0", "success", flows);
    }


    @RequestMapping(value = "/updateMasterFlow", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "更新主版本的flow")
    @ResponseBody
    public Map updateMasterFlow(@RequestBody Flow flow) {
        if (StringUtils.isEmpty(flow.getId())) {
            return this.getRtn(BaseController.REQUEST_ERROR, "flow id不能为空");
        }
        ExecuteResult executeResult = this.flowManager.updateMasterFlow(flow);
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "req上线")
    @RequestMapping(value = "/operateForReqOnline", method = RequestMethod.GET)
    @ResponseBody
    public Map operateForReqOnline(@ApiParam(value = "reqIds，上线的reqIds") @RequestParam(value = "reqIds", required = true) String reqIds) {
        if (StringUtils.isEmpty(reqIds)) {
            return this.getRtn(BaseController.REQUEST_ERROR, "reqIds不能为空");
        }
        List<String> reqIdLst = Arrays.asList(reqIds.split(","));
        ExecuteResult executeResult = this.flowManager.operateForReqOnline(reqIdLst);
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }

    private static final class ReqFlowSequence {
        private String reqId;
        private List<String> flowIds;

        public String getReqId() {
            return reqId;
        }

        public void setReqId(String reqId) {
            this.reqId = reqId;
        }

        public List<String> getFlowIds() {
            return flowIds;
        }

        public void setFlowIds(List<String> flowIds) {
            this.flowIds = flowIds;
        }
    }

    @RequestMapping(value = "/updateSequenceOfReqFlow", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "更新req的flow顺序")
    @ResponseBody
    public Map updateSequenceOfReqFlow(@RequestBody ReqFlowSequence reqFlowSequence) {
        String reqId = reqFlowSequence.getReqId();
        List<String> flowIds = reqFlowSequence.getFlowIds();
        if (StringUtils.isEmpty(reqId) || CollectionUtils.isEmpty(flowIds)) {
            return this.getRtn(BaseController.REQUEST_ERROR, "参数不能为空");
        }
        ExecuteResult executeResult = this.flowManager.updateSequenceOfReqFlow(reqId, flowIds);
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }

    @RequestMapping(value = "/getFlowFeatures", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获得flow指定的feature")
    @ResponseBody
    public Map getFlowFeatures(@ApiParam(value = "flowId", required = true) @RequestParam(value = "flowId", required = true) String flowId,
                               @ApiParam(value = "reqId,缺省为-1", required = false) @RequestParam(value = "reqId", defaultValue = "-1") String reqId) {

        ExecuteResult executeResult = null;
        try {
            executeResult = this.flowManager.getFlowFeatures(flowId, reqId);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return this.getRtn("1", e.getMessage());
        }
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }

    @RequestMapping(value = "/operateForFeatureModify", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "req关联/修改feature时调用")
    @ResponseBody
    public Map operateForFeatureModify(@ApiParam(value = "reqId", required = true) @RequestParam(value = "reqId", required = true) String reqId,
                                       @ApiParam(value = "featureId", required = true) @RequestParam(value = "featureId", required = true) String featureId) {

        ExecuteResult executeResult = null;
        try {
            executeResult = this.flowManager.operateForFeatureModify(reqId, featureId);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return this.getRtn("1", e.getMessage());
        }
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }


    @RequestMapping(value = "/reqSubmit", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "reqSubmit时调用")
    @ResponseBody
    public Map reqSubmit(@ApiParam(value = "reqId", required = true) @RequestParam(value = "reqId", required = true) String reqId,
                         @ApiParam(value = "version", required = false) @RequestParam(value = "version", required = false) String version) {

        ExecuteResult executeResult = null;
        try {
            executeResult = this.flowManager.reqSubmit(reqId, version);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return this.getRtn("1", e.getMessage());
        }
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }

    //    @ResponseStatus(HttpStatus.OK)
//    @ApiOperation(value = "获取的submit历史版本")
//    @RequestMapping(value = "/getSubmitHistory", method = RequestMethod.GET)
//    @ResponseBody
    public Map getSubmitHistory(@ApiParam(value = "reqId", required = false) @RequestParam(value = "reqId", required = false) String reqId,
                                @ApiParam(value = "flowId", required = true) @RequestParam(value = "flowId", required = true) String featureId) {

        return this.getRtn("0", "sus", this.flowManager.getSubmitHistory(featureId, reqId));
    }

    //    @Deprecated
//    @ResponseStatus(HttpStatus.OK)
//    @ApiOperation(value = "查询功能点关联了多少flow")
//    @RequestMapping(value = "/getFlowNumOfFeature", method = RequestMethod.GET)
//    @ResponseBody
//    public Map getFlowNumOfFeature( @ApiParam(value = "reqId, 缺省为-1", required = false) @RequestParam(value = "reqId", defaultValue = "-1") String reqId,
//                                 @ApiParam(value = "featureId", required = true) @RequestParam(value = "featureId", required = true) String featureId) {
//
//        return this.getRtn("0", "success", this.flowManager.getFlowNumOfFeature(featureId, reqId));
//    }
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "查询功能点关联的flow")
    @RequestMapping(value = "/getFlowsOfFeature", method = RequestMethod.GET)
    @ResponseBody
    public Map getFlowsOfFeature(@ApiParam(value = "reqId, 缺省为-1", required = false) @RequestParam(value = "reqId", defaultValue = "-1") String reqId,
                                 @ApiParam(value = "featureId", required = true) @RequestParam(value = "featureId", required = true) String featureId) {

        return this.getRtn("0", "success", this.flowManager.getFlowsOfFeature(featureId, reqId));
    }


    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取所有的FlowFrame, flow元素")
    @RequestMapping(value = "/getAllElements", method = RequestMethod.GET)
    @ResponseBody
    public Map getAllElements() {
        ExecuteResult executeResult = this.flowManager.getAllElements();
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }


    public static class FlowVersionVo {
        private String flowId;
        private String reqId;
        private String version;
        private String reqName;
        private Map<String, Object> attrs;

        public String getFlowId() {
            return flowId;
        }

        public void setFlowId(String flowId) {
            this.flowId = flowId;
        }

        public String getReqId() {
            return reqId;
        }

        public void setReqId(String reqId) {
            this.reqId = reqId;
        }

        public String getVersion() {
            return version;
        }

        public void setVersion(String version) {
            this.version = version;
        }

        public String getReqName() {
            return reqName;
        }

        public void setReqName(String reqName) {
            this.reqName = reqName;
        }

        public Map<String, Object> getAttrs() {
            return attrs;
        }

        public void setAttrs(Map<String, Object> attrs) {
            this.attrs = attrs;
        }
    }

    /**
     * 获得所有的flow version(包括master, req)
     *
     * @return
     */
    @RequestMapping(value = "/getAllFlowVersions", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取Flow的版本地图")
    @ResponseBody
    public Map getAllFlowVersions(@ApiParam(value = "flowId", required = true) @RequestParam(value = "flowId", required = true) String flowId) {
        Map<String, Object> result = null;
        try {
            result = this.flowManager.getAllFlowVersions(flowId);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return this.getRtn(BaseController.REQUEST_ERROR, e.getMessage());
        }
        return this.getRtn(BaseController.REQUEST_SUCCESS, "success!", result);
    }


    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "req提交feature(暂时供测试生成数据用)")
    @RequestMapping(value = "/submit", method = RequestMethod.GET)
    @ResponseBody
    public Map submit(@ApiParam(value = "reqId，reqId", required = true) @RequestParam(value = "reqId", required = true) String reqId,
                      @ApiParam(value = "flowId，flow id", required = true) @RequestParam(value = "flowId", required = true) String flowId) {


        ExecuteResult executeResult = new ExecuteResult();
        try {
            this.flowManager.submit(flowId, reqId, null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            executeResult.toError(e.getMessage());
        }
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }


    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取最新提交的flow")
    @RequestMapping(value = "/getLatestSubmitFlow", method = RequestMethod.GET)
    @ResponseBody
    public Map getLatestSubmitFlow(@ApiParam(value = "reqId", required = true) @RequestParam(value = "reqId", required = true) String reqId,
                                   @ApiParam(value = "flowId", required = true) @RequestParam(value = "flowId", required = true) String flowId) {
        ExecuteResult executeResult = this.flowManager.getLatestSubmitFlow(flowId, reqId);
        return this.getRtn(executeResult.getCode(), executeResult.getDesc(), executeResult.getData());
    }


    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取req最新版本提交的flow")
    @RequestMapping(value = "/getReqLatestSubmitFlows", method = RequestMethod.GET)
    @ResponseBody
    public Map getReqLatestSubmitFlows(@ApiParam(value = "reqId", required = true) @RequestParam(value = "reqId", required = true) String reqId) {
        List<Flow> flows = null;
        try {
            flows = this.flowManager.getReqLatestSubmitFlows(reqId);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return this.getRtn(BaseController.REQUEST_ERROR, e.getMessage());
        }
        return this.getRtn(BaseController.REQUEST_SUCCESS, "success!", flows);
    }
}
